package com.hzncc.scaffold.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.util.StringUtil;
import com.hzncc.scaffold.core.ResultT;
import com.hzncc.scaffold.entity.Other.*;
import com.hzncc.scaffold.entity.Vo.*;
import com.hzncc.scaffold.mapper.CourseMapper;
import com.hzncc.scaffold.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzncc.scaffold.utils.FileUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.error.YAMLException;

import java.util.*;

/**
 * <p>
 * 课程表 服务实现类
 * </p>
 *
 * @author DrunkBear
 * @since 2022-04-27
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {

    @Autowired
    CourseService courseService;

    @Autowired
    PaperrecordService paperrecordService;

    @Autowired
    CoursemajorService coursemajorService;

    @Autowired
    MajorService majorService;

    @Autowired
    QuestionService questionService;

    @Autowired
    PaperService paperService;

    @Autowired
    TaskprogressService taskprogressService;


    @Autowired
    private TaskService taskService;

    @Autowired
    private ExerciserecordService exerciserecordService;


    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public ResultT saveCourse(Course course) {
        course.setCreateTime(DateUtil.now());

        boolean save = courseService.save(course);
        if (save) {
            return ResultT.success("新增成功");
        } else {
            return ResultT.fail("新增失败");
        }
    }

    @Override
    public ResultT updateCourse(Course course) {
        boolean update = courseService.updateById(course);
        if (update) {
            return ResultT.success("修改成功");
        } else {
            return ResultT.fail("修改失败");
        }
    }


    @Override
    public ResultT deleteCourse(Integer courseId) {
        if (courseService.getById(courseId) != null) {
            Course course = courseService.getById(courseId);
            course.setIsDelete(1);
            boolean update = courseService.updateById(course);
            if (update) {
                return ResultT.success("删除成功");
            } else {
                return ResultT.fail("删除失败");
            }
        } else {
            return ResultT.fail("数据错误");
        }
    }

    @Override
    public ResultT search(Course course) {
        LambdaQueryWrapper<Course> lqw = new LambdaQueryWrapper<>();
        lqw.eq(course.getId() != null, Course::getId, course.getId());
        lqw.like(course.getTitle() != null, Course::getTitle, course.getTitle());
        lqw.eq(course.getCover() != null, Course::getCover, course.getCover());
        lqw.eq(course.getTeacher() != null, Course::getTeacher, course.getTeacher());
        lqw.eq(course.getTeacherInfo() != null, Course::getTeacherInfo, course.getTeacherInfo());
        lqw.eq(course.getCourseInfo() != null, Course::getCourseInfo, course.getCourseInfo());
        lqw.eq(course.getAuthentation() != null, Course::getAuthentation, course.getAuthentation());
        lqw.eq(course.getPublisherId() != null, Course::getPublisherId, course.getPublisherId());
        lqw.eq(course.getStatus() != null, Course::getStatus, course.getStatus());
        lqw.eq(course.getPubTime() != null, Course::getPubTime, course.getPubTime());
        lqw.eq(course.getJoinedNum() != null, Course::getJoinedNum, course.getJoinedNum());
        lqw.eq(course.getCreateTime() != null, Course::getCreateTime, course.getCreateTime());
        lqw.eq(course.getStayAtTop() != null, Course::getStayAtTop, course.getStayAtTop());
        lqw.eq(course.getSortTime() != null, Course::getSortTime, course.getSortTime());
        lqw.eq(course.getIsDelete() != null, Course::getIsDelete, course.getIsDelete());
        lqw.eq(course.getIsFree() != null, Course::getIsFree, course.getIsFree());
        lqw.eq(course.getCertTemplate() != null, Course::getCertTemplate, course.getCertTemplate());
        lqw.eq(course.getSetWidth() != null, Course::getSetWidth, course.getSetWidth());
        lqw.eq(course.getSetHeight() != null, Course::getSetHeight, course.getSetHeight());
        lqw.eq(course.getCoordinate() != null, Course::getCoordinate, course.getCoordinate());
        lqw.eq(course.getIsQuestionLibExercise() != null, Course::getIsQuestionLibExercise, course.getIsQuestionLibExercise());

        List<Course> courseList = courseService.list(lqw);
        return ResultT.success(courseList);
    }

    @Override
    public ResultT commit(CommitCourseVo commitCourseVo) {
        Course course = BeanUtil.toBean(commitCourseVo, Course.class);
        course.setCreateTime(DateUtil.now());
        LambdaQueryWrapper<Major> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Major::getId, commitCourseVo.getModule());
        Major one = majorService.getOne(lqw);
        if (BeanUtil.isEmpty(one)) {
            return ResultT.fail("未在专业中找到该模块");
        }
        if (one.getName().equals("题库训练")) {
            course.setIsQuestionLibExercise(1);
        }
        if (one.getName().equals("考试模块")) {
            course.setIsQuestionLibExercise(2);
        }
        if (null != course.getCover()) {
            course.setCover(FileUtil.urlLastName(course.getCover()));
        }
        course.setSortTime(DateUtil.now());
        boolean save = courseService.save(course);
        if (save) {
            Map<String, Integer> map = new HashMap<>();
            map.put("courseId",Integer.valueOf(course.getId()));
            return ResultT.success(map);
        } else {
            return ResultT.fail("保存失败");
        }
    }

    @Override
    public List<CourseDataListVo> courseDataList(Integer pageNum, Integer pageSize, String keyword, String startTime, String endTime, Integer majorId) {
//        if (pageNum != null && pageSize != null && pageNum > 0 && pageSize > 0) {
//            PageHelper.startPage(pageNum, pageSize);
//        }
        QueryWrapper<Course> qw = new QueryWrapper<>();
        qw.eq("course.isDelete", 0);
        qw.eq("course.status", 1);
        List<Course> courseList = courseService.list(qw);


        ArrayList<CourseDataListVo> courseDataListVos = new ArrayList<>();

        for (Course course : courseList) {
            CourseDataListVo courseDataListVo = new CourseDataListVo();
            courseDataListVo.setId(course.getId());
            courseDataListVo.setTitle(course.getTitle());
            courseDataListVo.setJoinedNum(course.getJoinedNum());

            LambdaQueryWrapper<Paperrecord> lqw = new LambdaQueryWrapper<>();
            lqw.eq(Paperrecord::getCourseId, course.getId());
            int recordNum = paperrecordService.count(lqw);
            lqw.eq(Paperrecord::getPassed, course.getId());
            int certNum = paperrecordService.count(lqw);
            courseDataListVo.setRecordNum(recordNum);
            courseDataListVo.setCertNum(certNum);

            lqw.eq(Paperrecord::getPassed, 1);
            int passedNum = paperrecordService.count(lqw);
            courseDataListVo.setPassedNum(passedNum);

            ArrayList<Major> majors = new ArrayList<>();

            ArrayList<Integer> majorIdList = new ArrayList<>();
            LambdaQueryWrapper<Coursemajor> lqww = new LambdaQueryWrapper<>();
            lqww.eq(Coursemajor::getCourseId, course.getId());
            List<Coursemajor> coursemajors = coursemajorService.list(lqww);
            for (Coursemajor coursemajor : coursemajors) {
                if (majorService.getById(coursemajor.getMajorId()) != null) {
                    Major major = majorService.getById(coursemajor.getMajorId());
                    majorIdList.add(coursemajor.getMajorId());
                    majors.add(major);
                }
            }
            courseDataListVo.setMajors(majors);
            courseDataListVo.setUnpassedNum(recordNum - passedNum);

            if (StrUtil.isNotEmpty(startTime) && StrUtil.isNotEmpty(endTime)) {
                if (!DateUtil.isIn(DateUtil.parse(course.getCreateTime(), "yyyy-MM-dd"), DateUtil.parse(startTime, "yyyy-MM-dd"), DateUtil.parse(endTime, "yyyy-MM-dd"))) {
                    continue;
                }
            }
            if (majorId != null) {
                if (!CollUtil.contains(majorIdList, majorId)) {
                    continue;
                }
            }
            courseDataListVos.add(courseDataListVo);
        }
        return courseDataListVos;
    }

    @Override
    public ResultT commitPaper(ScheduledAnswerVo scheduledAnswerVo) {

        Paperrecord paperrecord = new Paperrecord();
        paperrecord.setCourseId(Integer.parseInt(scheduledAnswerVo.getCourseId()));
        paperrecord.setPaperId(Integer.parseInt(scheduledAnswerVo.getPaperId()));
        paperrecord.setTaskId(Integer.parseInt(scheduledAnswerVo.getTaskId()));
        paperrecord.setTimeUse(scheduledAnswerVo.getTimeUse().toString());
        paperrecord.setCreateTime(DateUtil.now());


        String userAnswer = scheduledAnswerVo.getUserAnswer();

        //AES解密
        AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, "w2SIy2Hx%2i!tTCd-ikwHEv_kQmB58xI".getBytes(), "R7#54X&gLB!6Q&s=".getBytes());
        userAnswer = aes.decryptStr(userAnswer, CharsetUtil.CHARSET_UTF_8);
        paperrecord.setUserAnswer(userAnswer);

        //计算得分
        if (paperService.getById(scheduledAnswerVo.getPaperId()) == null) {
            return ResultT.fail("数据错误");
        }
        Paper paper = paperService.getById(scheduledAnswerVo.getPaperId());

        Integer passScore = paper.getPassScore();

        Integer perSingle = paper.getPerSingle();
        Integer perMulti = paper.getPerMulti();
        Integer perJudge = paper.getPerJudge();
        Integer perOperation = paper.getPerOperation();

        //总分
        Integer theoryScore = 0;

        JSONArray jsonArray = new JSONArray(userAnswer);
        List<PaperAnswerVo> paperAnswerVos = JSONUtil.toList(jsonArray, PaperAnswerVo.class);

        for (PaperAnswerVo paperAnswerVo : paperAnswerVos) {
            if (questionService.getById(paperAnswerVo.getId()) != null) {
                Question question = questionService.getById(paperAnswerVo.getId());
                if (StrUtil.equals(question.getAnswer(), paperAnswerVo.getAnswer())) {
                    //单选题
                    if (question.getType() == 0) {
                        theoryScore += perSingle;
                    }
                    if (question.getType() == 1) {
                        theoryScore += perMulti;
                    }
                    if (question.getType() == 2) {
                        theoryScore += perJudge;
                    }
                }
            }
        }

        paperrecord.setUserId(StpUtil.getLoginIdAsInt());
        paperrecord.setTheoryScore(theoryScore);
        if (theoryScore >= passScore) {
            paperrecord.setPassed(1);
        } else {
            paperrecord.setPassed(0);
        }

        boolean save = paperrecordService.save(paperrecord);

        if (save) {
            LambdaQueryWrapper<Taskprogress> lqw = new LambdaQueryWrapper<>();
            lqw.eq(Taskprogress::getUserId, StpUtil.getLoginIdAsInt());
            lqw.eq(Taskprogress::getTaskId, scheduledAnswerVo.getTaskId());
            lqw.eq(Taskprogress::getCourseId, scheduledAnswerVo.getCourseId());

            Taskprogress taskprogress = taskprogressService.getOne(lqw);
            taskprogress.setIsFinished(false);
            taskprogressService.updateById(taskprogress);

            return ResultT.success("操作成功");
        } else {
            return ResultT.fail("操作失败");
        }
    }


    @Override
    public ResultT tasKcommitPaper(ScheduledAnswerVo scheduledAnswerVo) {

        Paper paper = paperService.getById(scheduledAnswerVo.getPaperId());
        Integer perSingle = paper.getPerSingle();
        Integer perMulti = paper.getPerMulti();
        Integer perJudge = paper.getPerJudge();
        List<Question> paperJson = JSONUtil.toList(paper.getTheoryQuestion(), Question.class);
        Integer passScore = paper.getPassScore();
        Integer perOperation = paper.getPerOperation();
        if (StringUtils.isNotEmpty(scheduledAnswerVo.getUserAnswer())) {
            //AES解密
            AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, "w2SIy2Hx%2i!tTCd-ikwHEv_kQmB58xI".getBytes(), "R7#54X&gLB!6Q&s=".getBytes());
            String userAnswer = aes.decryptStr(scheduledAnswerVo.getUserAnswer(), CharsetUtil.CHARSET_UTF_8);
            //总分
            Integer theoryScore = 0;
            List<PaperAnswerVo> answerJson = JSONUtil.toList(userAnswer, PaperAnswerVo.class);
            if (CollUtil.isNotEmpty(answerJson)) {
                for (PaperAnswerVo paperAnswerVo : answerJson) {
                    for (Question answerVo : paperJson) {
                        if (paperAnswerVo.getId().equals(answerVo.getId())) {
                            if (StringUtils.isNotEmpty(paperAnswerVo.getAnswer()) && paperAnswerVo.getAnswer().equals(answerVo.getAnswer())) {
                                //单选题
                                if (answerVo.getType() == 0) {
                                    theoryScore += perSingle;
                                }
                                if (answerVo.getType() == 1) {
                                    theoryScore += perMulti;
                                }
                                if (answerVo.getType() == 2) {
                                    theoryScore += perJudge;
                                }
                            }
                        }
                    }
                }
            }

            Integer passed = 0;
            Task examTask = taskService.getById(scheduledAnswerVo.getTaskId());
            if (BeanUtil.isNotEmpty(examTask) && examTask.getExamType().equals(0)) {
                passed = (theoryScore < passScore) ? 0 : 1;
            }
            String now = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
            if (scheduledAnswerVo.getType().equals(3)) {
                LambdaQueryWrapper<Paperrecord> pap = new LambdaQueryWrapper<>();
                pap.eq(Paperrecord::getUserId, StpUtil.getLoginIdAsInt());
                pap.eq(Paperrecord::getCourseId, scheduledAnswerVo.getCourseId());
                Paperrecord isExist = paperrecordService.getOne(pap);
                if (BeanUtil.isNotEmpty(isExist)) {
                    LambdaQueryWrapper<Taskprogress> lqw = new LambdaQueryWrapper<>();
                    lqw.eq(Taskprogress::getUserId, StpUtil.getLoginIdAsInt());
                    lqw.eq(Taskprogress::getTaskId, scheduledAnswerVo.getTaskId());
                    Taskprogress taskprogress = taskprogressService.getOne(lqw);
                    if (BeanUtil.isNotEmpty(taskprogress) && !taskprogress.getIsFinished()) {
                        isExist.setTheoryScore(theoryScore);
                        isExist.setPaperId(Integer.valueOf(scheduledAnswerVo.getPaperId()));
                        isExist.setPassed(passed);
                        isExist.setTimeUse(scheduledAnswerVo.getTimeUse().toString());
                        isExist.setUserAnswer(userAnswer);   //修改成了解密之后的数据
                        isExist.setCreateTime(now);
                        isExist.setTaskId(Integer.valueOf(scheduledAnswerVo.getTaskId()));
//                        if (!isExist.getResetted()) {
//                            isExist.setResetted(true);
//                        }
                        if(passed == 0 ){
                            isExist.setResetted(false);
                        }
                        paperrecordService.updateById(isExist);
                    } else {
                        return ResultT.success("当前用户已存在考试记录");
                    }
                } else {
                    Paperrecord paperrecord = new Paperrecord();
                    paperrecord.setTheoryScore(theoryScore);
                    paperrecord.setPaperId(Integer.parseInt(scheduledAnswerVo.getPaperId()));
                    paperrecord.setPassed(passed);
                    paperrecord.setUserId(StpUtil.getLoginIdAsInt());
                    paperrecord.setCourseId(Integer.parseInt(scheduledAnswerVo.getCourseId()));
                    paperrecord.setTaskId(Integer.parseInt(scheduledAnswerVo.getTaskId()));
                    paperrecord.setTimeUse(scheduledAnswerVo.getTimeUse().toString());
                    paperrecord.setCreateTime(now);
                    paperrecord.setUserAnswer(userAnswer);
                    paperrecordService.save(paperrecord);
                }

            } else if (scheduledAnswerVo.getType().equals(2)) {
                LambdaQueryWrapper<Exerciserecord> exerciserecordLambda = new LambdaQueryWrapper<>();
                exerciserecordLambda.eq(Exerciserecord::getUserId, StpUtil.getLoginIdAsInt());
                exerciserecordLambda.eq(Exerciserecord::getTaskId, scheduledAnswerVo.getTaskId());
                Exerciserecord isExist = exerciserecordService.getOne(exerciserecordLambda);
                if (BeanUtil.isNotEmpty(isExist)) {
                    isExist.setTheoryScore(theoryScore);
                    isExist.setPaperId(Integer.valueOf(scheduledAnswerVo.getPaperId()));
                    isExist.setPassed(passed);
                    isExist.setTimeUse(scheduledAnswerVo.getTimeUse().toString());
                    isExist.setCreateTime(now);
                    exerciserecordService.updateById(isExist);
                } else {
                    Exerciserecord exerciserecord = new Exerciserecord();
                    exerciserecord.setTheoryScore(theoryScore);
                    exerciserecord.setPaperId(Integer.valueOf(scheduledAnswerVo.getPaperId()));
                    exerciserecord.setPassed(passed);
                    exerciserecord.setUserId(StpUtil.getLoginIdAsInt());
                    exerciserecord.setTaskId(Integer.valueOf(scheduledAnswerVo.getTaskId()));
                    exerciserecord.setTimeUse(scheduledAnswerVo.getTimeUse().toString());
                    exerciserecord.setUserAnswer(userAnswer);
                    exerciserecord.setCreateTime(now);
                    exerciserecordService.save(exerciserecord);
                }
            }
            String uniqueStr = scheduledAnswerVo.getCourseId() + '-' + scheduledAnswerVo.getTaskId() + '-' + scheduledAnswerVo.getPaperId() + '-' + StpUtil.getLoginIdAsInt();
            String scheduledData = (String) redisTemplate.opsForValue().get(uniqueStr);
            if(StringUtils.isNotEmpty(scheduledData)){
                redisTemplate.delete(uniqueStr);
            }
        }
        return ResultT.success();
    }
}
